package com.bbg.amyam.web.util.view;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.roo.support.util.XmlElementBuilder;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.bbg.amyam.web.util.menu.MenuItem;

public class StandardViewFilesCopier extends ViewFilesCopier{
	private static final Log log = LogFactory.getLog(StandardViewFilesCopier.class);

	
	public StandardViewFilesCopier(MenuItem menuItem, File templateDir,
			File destDir, File viewRootcDir) {
		super(menuItem,templateDir,destDir,viewRootcDir);
	}

	public void doCopy(boolean overwrite) throws IOException {
		File templateView=FileUtils.getFile(templateDir, "index.jspx");
		File viewSrcDir=new File(viewRootcDir,this.menuItem.getDomain().toLowerCase()+"s");
		Collection<File> views = FileUtils.listFiles(viewSrcDir, new String[] {"jspx"}, false);
		ArrayList<String> viewNames=new ArrayList<String>();
		for(File srcView:views){
			log.debug("Copying "+srcView.getPath()+File.separator+ srcView.getName()+"s");
			String fileName=srcView.getName();
			fileName=fileName.equals("list.jspx")?"index.jspx":fileName;
			
			File destView = new File(destDir, fileName);
			
			if(destView.exists()){
				if(overwrite){
					destView.deleteOnExit();
					log.debug("Removed existing "+destView.getPath());
				}else{
					log.debug("Ignored existing "+fileName+" since it exists");
					continue;
				}
			}else{
				viewNames.add(StringUtils.replace(fileName, ".jspx", ""));
			}
			manpulateStandardView(templateView,destView,srcView);
		}
		
		File viewDefDest=new File(destDir,"views.xml");
		if(!viewDefDest.exists()){
			File viewDefSrc=new File(templateDir,"views.xml");
			FileUtils.copyFile(viewDefSrc, viewDefDest);
			log.debug("Created " + viewDefDest.getPath());
		}
		
		updateViewDef(viewDefDest,viewNames);
		
	}

	private void updateViewDef(File viewDefFile, ArrayList<String> viewNames) throws IOException {
		InputStream filesInputSream = FileUtils.openInputStream(viewDefFile);
		Document viewDefDoc = XmlUtils.readXml(filesInputSream);
		
		Element root = viewDefDoc.getDocumentElement();
		NodeList nodes = root.getChildNodes();

		for (int index = 0; index < nodes.getLength(); index++) {
			Node node = nodes.item(index);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				NamedNodeMap atts = node.getAttributes();
				Node att = atts.getNamedItem("name");
				String nameValue=att.getNodeValue();
				if (att!=null && StringUtils.contains(nameValue, "__target__name__")) {
					root.removeChild(node);
				}
				if(viewNames.contains(nameValue)){
					viewNames.remove(nameValue);
				}
			}
		}
		String module = this.menuItem.getTargetParent();

		String targetName=StringUtils.replace(this.menuItem.getTarget(), "*", "");
		
		
		for(String viewName:viewNames){
			XmlElementBuilder builder = new XmlElementBuilder("definition", viewDefDoc);
			builder.addAttribute("extends", module);
			builder.addAttribute("name", targetName+"/"+viewName);
			
			XmlElementBuilder attributeBuilder = new XmlElementBuilder("put-attribute", viewDefDoc);
			attributeBuilder.addAttribute("name", "body");
			attributeBuilder.addAttribute("value", "/WEB-INF/views/amyamviews/"+targetName+"/"+viewName+".jspx");

			builder.addChild(attributeBuilder.build());
			viewDefDoc.getDocumentElement().appendChild(builder.build());
		}
		

		FileOutputStream filesOutputSream = FileUtils.openOutputStream(viewDefFile);
		XmlUtils.writeFormattedXml(filesOutputSream, viewDefDoc);
		log.debug("Updated " + viewDefFile.getPath());
	}

	private void manpulateStandardView(File templateView, File destView,
			File srcView) throws IOException {
		
		InputStream filesInputSream = FileUtils.openInputStream(templateView);
		Document templateDoc = XmlUtils.readXml(filesInputSream);
		
		removeDefaultNodes(templateDoc);
		
			XmlElementBuilder builder = new XmlElementBuilder("spring:message", templateDoc);
			builder.addAttribute("code", "amyam_label_"+this.menuItem.getId());
			builder.addAttribute("htmlEscape", "false");
			builder.addAttribute("var", "title");
			
			Element element = builder.build();
			templateDoc.getDocumentElement().appendChild(element);
			
			builder = new XmlElementBuilder("util:panel",templateDoc);
			builder.addAttribute("id", "title");
			builder.addAttribute("title", "${title}");
			
			Node srcNode=getNodeFromSrcDoc(srcView);
			if(srcNode!=null){
				updateSrcNode(srcNode);
				Node importedSrcNode = templateDoc.importNode(srcNode, true);
				builder.addChild(importedSrcNode);
			}
			element = builder.build();
			templateDoc.getDocumentElement().appendChild(element);
		
		FileOutputStream filesOutputSream = FileUtils.openOutputStream(destView);
		XmlUtils.writeFormattedXml(filesOutputSream, templateDoc);
		log.debug("Copied " + destView.getPath());
	}
	
	private void updateSrcNode(Node srcNode) {
		NamedNodeMap atts = srcNode.getAttributes();
		if(atts!=null){
		Node pathAtt = atts.getNamedItem("path");
		if(pathAtt!=null){
			String path="/${menuDescriptor.currentUnitName}/"+this.menuItem.getTarget();
			pathAtt.setNodeValue(path);
		}		
		}
		NodeList children = srcNode.getChildNodes();
		for(int index=0;index<children.getLength();index++){
			Node child = children.item(index);
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				NamedNodeMap childAtts = child.getAttributes();
				Node fieldAtt = childAtts.getNamedItem("field");
				if(fieldAtt!=null){
					String field=fieldAtt.getNodeValue();
					if(this.menuItem.isExculededDomainField(field)){
						srcNode.removeChild(child);
					}
				}
				
				fieldAtt = childAtts.getNamedItem("property");
				if(fieldAtt!=null){
					String field=fieldAtt.getNodeValue();
					if(this.menuItem.isExculededDomainField(field)){
						srcNode.removeChild(child);
					}
				}
				
			}
			
			updateSrcNode(child);
		}
	}

	private Node getNodeFromSrcDoc(File srcView) throws IOException {
		InputStream filesInputSream = FileUtils.openInputStream(srcView);
		Document templateDoc = XmlUtils.readXml(filesInputSream);
		
		Element root = templateDoc.getDocumentElement();
		NodeList nodes = root.getChildNodes();
		int count = nodes.getLength();
		for (int index = 0; index < count; index++) {
			Node node = nodes.item(index);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
			Node matchedNode=getDomainFormNode(node);
			if(matchedNode!=null){
				return matchedNode;
			}}
		}
		
		return null;
	}

	private Node getDomainFormNode(Node node) {
		if (node.getNodeType() == Node.ELEMENT_NODE) {
			NamedNodeMap atts = node.getAttributes();
			Node att = atts.getNamedItem("id");
			if (att!=null && StringUtils.contains(att.getNodeValue(), "com_bbg_amyam_domain_model")) {
				return node;
			}
		}
		
		if ( node.getNodeType() == Node.TEXT_NODE) {
			String value=node.getNodeValue();
			String name=node.getTextContent();
			
		}
		
		NodeList children = node.getChildNodes();
		int count = children.getLength();
		for(int index=0;index<count;index++){
			Node matchednode= getDomainFormNode(children.item(index));
			if(matchednode!=null){
				return matchednode;
			}
		}
		return null;
	}

	private void removeDefaultNodes(Document document) {
		Element root = document.getDocumentElement();
		NodeList nodes = root.getChildNodes();

		for (int index = 0; index < nodes.getLength(); index++) {
			Node node = nodes.item(index);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				NamedNodeMap atts = node.getAttributes();
				Node att = atts.getNamedItem("code");
				if (att!=null && StringUtils.contains(att.getNodeValue(), "amyam_label___menu__item__id__")) {
					root.removeChild(node);
				}
				att = atts.getNamedItem("id");
				if (att!=null && StringUtils.contains(att.getNodeValue(), "title")) {
					root.removeChild(node);
				}
				
			}

		}
	}

}
